package com.wwj.aicodemother.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.wwj.aicodemother.exception.BusinessException;
import com.wwj.aicodemother.exception.ErrorCode;
import com.wwj.aicodemother.exception.ThrowUtils;
import com.wwj.aicodemother.service.ProjectDownloadService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Set;

@Service
@Slf4j
public class ProjectDownloadServiceimpl implements ProjectDownloadService {
    /**
     * 需要过滤的文件和目录名称
     */
    private static final Set<String> IGNORED_NAME = Set.of(
            "node_modules",
            ".git",
            "dist",
            "build",
            ".DS_Store",
            ".env",
            "target",
            ".mvn",
            ".idea",
            ".vscode"
    );

    private static final Set<String> IGNORED_EXTENDSION = Set.of(
            ".log",
            ".tmp",
            ".cache"
    );


    /**
     * 下载项目为zip
     *
     * @param projectPath
     * @param downloadFileName
     * @param response
     * @return
     */
    @Override
    public void downloadProjectAsZip(String projectPath, String downloadFileName, HttpServletResponse response) {
        //基础校验
        ThrowUtils.throwIf(StrUtil.isBlank(projectPath), ErrorCode.PARAMS_ERROR,"下载文件名不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(downloadFileName), ErrorCode.PARAMS_ERROR,"下载文件名不能为空");
        File projectDir = new File(projectPath);
        ThrowUtils.throwIf(!projectDir.exists(), ErrorCode.PARAMS_ERROR,"项目路径不存在");
        ThrowUtils.throwIf(!projectDir.isDirectory(), ErrorCode.PARAMS_ERROR,"项目路径不是一个目录");
        log.info("开始下载项目:{} -> {}.zip",projectPath,downloadFileName);
        //设置HTTP响应头
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType("application/zip");
        response.addHeader("Content-Disposition",
                String.format("attachment; filename=\"%s.zip\"", downloadFileName));
        //定义文件过滤器
        FileFilter filter = file -> isPathAllowed(projectDir.toPath(),file.toPath());
        //压缩
        try {
            //使用 Hutool 的ZipUtil 直接将过滤后的目录压缩到响应输出流
            ZipUtil.zip(response.getOutputStream(), StandardCharsets.UTF_8,false,filter,projectDir);
            log.info("打包下载成功：{} -> {}.zip",projectPath,downloadFileName);
        } catch (IOException e) {
            log.info("下载项目失败:{}",e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"下载项目失败");
        }
    }

    /**
     * 检验路径
     * @param projectRoot 项目根目录
     * @param fullPath  完整路径
     * @return 是否允许
     */
    private boolean isPathAllowed(Path projectRoot,Path fullPath){
        Path relativizePath = projectRoot.relativize(fullPath);
        //检查路径中的每一部分是否符合要求
        for (Path part : relativizePath) {
            String partName = part.toString();
            //检查是否在忽略名称列表中
            if(IGNORED_NAME.contains(partName)){
                return false;
            }
            //检查是否在忽略扩展名列表中
            if(IGNORED_EXTENDSION.stream().anyMatch(ext -> partName.toLowerCase().endsWith(ext))){
                return false;
            }
        }
        return true;
    }
}
